package com.wongoing.jwt;

import java.security.Key;
import java.util.Date;

import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;

import org.apache.log4j.Logger;

import com.wongoing.bus.util.Constants;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.CompressionCodecs;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

/*
 * JSON Web Token（JWT）
1.Header 
包括类别、加密算法
{
"typ": "JWT",
"alg": "HS256"
}
2.Payload/Claims
包括需要传递的用户信息
{ "iss": "Online JWT Builder",  该JWT的签发者，是否使用是可选的；
  "iat": 1416797419, 在什么时候签发的(UNIX时间)，是否使用是可选的；
  "exp": 1448333419, 什么时候过期，这里是一个Unix时间戳，是否使用是可选的；
  "aud": "www.example.com", 接收该JWT的一方，是否使用是可选的；
  "sub": "jrocket@example.com", 该JWT所面向的用户，是否使用是可选的；
  "GivenName": "Johnny", 
  "Surname": "Rocket", 
  "Email": "jrocket@example.com", 
  "Role": [ "Manager", "Project Administrator" ] 
}
3. Signature
根据alg算法与私有秘钥进行加密得到的签名字串；
这一段是最重要的敏感信息，只能在服务端解密；
HMACSHA256(  
    base64UrlEncode(header) + "." +
    base64UrlEncode(payload),
    SECREATE_KEY
)
 */
public class BaseTokenManager {

	private static final Logger logger = Logger.getLogger(BaseTokenManager.class);

	public String createToken(String userName, Date iat, Date exp) {
		
		//The JWT signature algorithm we will be using to sign the token
	    SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS512;

	    //We will sign our JWT with our ApiKey secret
	    byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(Constants.JWT_SECRET_KEY);
	    Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());
	    
	    JwtBuilder builder = Jwts.builder()
	    		.setIssuer(Constants.JWT_ISSUER) // 签发者
	    		.setIssuedAt(iat)
	    		.setSubject(userName) // 签发给哪个用户
	    		.compressWith(CompressionCodecs.DEFLATE)
	    		.signWith(signatureAlgorithm, signingKey); //SECRET_KEY是加密算法对应的密钥，这里使用的是HS512加密算法
		
		//Builds the JWT and serializes it to a compact, URL-safe string
		
	    return builder.compact();
	}

	protected Date createExpDate(long time) {
		long expMillis = System.currentTimeMillis() + time;
	    return new Date(expMillis);
	}
	
	protected String parseJWT(String jwt) {
		 
	    //This line will throw an exception if it is not a signed JWS (as expected)
	    Claims claims = Jwts.parser()         
	       .setSigningKey(DatatypeConverter.parseBase64Binary(Constants.JWT_SECRET_KEY))
	       .parseClaimsJws(jwt).getBody();

	    return claims.getSubject();
	}
}
